<!--
 * @Author: XNY
 * @Date: 2022-05-05 18:01:51
 * @LastEditTime: 2022-09-05 11:10:15
 * @LastEditors: Lw
 * @FilePath: \flood-prevention-web\src\components\From\index.vue
-->
<template>
  <!-- <div>
    <n-card size="small">
      
    </n-card>
  </div> -->
  <n-spin :show="loading">
    <n-form
      :inline="inline"
      ref="formRef"
      :model="form"
      :rules="rules"
      label-placement="left"
      class="x-form"
      :label-width="labelWidth"
    >
      <n-grid
        :cols="24"
        :x-gap="xGap"
        :y-gap="yGap"
        :collapsed="collapsed"
        :collapsed-rows="collapsedRows"
      >
        <n-form-item-gi
          v-for="(opt, idx) in options"
          :key="idx"
          :span="opt.span"
          :label="opt.label"
          :path="opt.key"
          :label-width="opt.labelWidth"
          @click="handleClick(opt.key)"
        >
          <!-- 查看模式 -->
          <template v-if="!['add', 'edit'].includes(type)">
            <slot v-if="opt.viewSlot" :name="opt.viewSlot">{{
              opt.viewSlot
            }}</slot>
            <span
              class="view-text"
              v-else-if="opt.type !== 'imgs' && opt.type !== 'file'"
              >{{ setViewSpan(opt) }}</span
            >
            <div v-else-if="opt.type === 'imgs'">
              <n-space>
                <n-image
                  v-for="item in form[opt.key] || []"
                  :key="item.url"
                  :width="80"
                  :height="80"
                  :src="item.url"
                />
              </n-space>
            </div>
            <div v-else-if="opt.type === 'file'">
              <a
                :download="item.fileName"
                target="_blank"
                class="enclosure"
                v-for="item in form[opt.key] || []"
                :key="item.url"
                :href="item.url"
                >{{ item.fileName }}</a
              >
            </div>
          </template>

          <!-- <template  v-if="!['add', 'edit'].includes(type)">
            <slot v-if="opt.viewSlot" :name="opt.viewSlot">{{opt.viewSlot}}</slot>
            <span v-else class="view-text">{{ setViewSpan(opt) }}</span>
          </template> -->

          <!-- 编辑模式 -->
          <!-- 输入框 -->
          <n-input
            v-else-if="['textarea', 'text', 'password'].includes(opt.type)"
            :type="opt.type"
            v-model:value="form[opt.key]"
            :inputProps="opt.inputProps"
            :size="opt.size || 'small'"
            :placeholder="opt.placeholder || '请输入'"
            show-password-on="click"
            :maxlength="opt.maxlength || 50"
            :disabled="opt.disabled || false"
            :clearable="opt.clearable === undefined ? true : opt.clearable"
            style="width: 100%"
            passively-activated
          >
            <template #suffix> {{ opt.unit }} </template>
          </n-input>
          <!-- 计数器 -->
          <n-input-number
            v-else-if="opt.type == 'number'"
            v-model:value="form[opt.key]"
            :inputProps="opt.inputProps"
            :max="opt.max"
            :min="opt.min"
            :clearable="opt.clearable === undefined ? true : opt.clearable"
            :size="opt.size || 'small'"
            :disabled="opt.disabled || false"
            :show-button="opt.showButton || false"
            :placeholder="opt.placeholder || '请输入'"
            style="width: 100%"
          >
            <template #suffix> {{ opt.unit }} </template>
          </n-input-number>
          <!-- mention -->
          <n-mention
            v-else-if="opt.type == 'mention'"
            v-bind="opt"
            type="text"
            v-model:value="form[opt.key]"
          />
          <!-- 单选 -->
          <n-radio-group
            v-model:value="form[opt.key]"
            v-else-if="opt.type == 'radio'"
            name="radiogroup"
          >
            <n-space>
              <n-radio
                v-for="song in opt.options"
                :key="song.value"
                :value="song.value"
                :disabled="song.disabled || false"
              >
                {{ song.label }}
              </n-radio>
            </n-space>
          </n-radio-group>
          <!-- 复选框 -->
          <n-checkbox-group
            v-model:value="form[opt.key]"
            v-else-if="opt.type == 'checkbox'"
          >
            <n-space>
              <n-checkbox
                v-for="song in opt.options"
                :key="song.value"
                :value="song.value"
                :disabled="song.disabled || false"
              >
                {{ song.label }}
              </n-checkbox>
            </n-space>
          </n-checkbox-group>
          <!-- 选择器 -->
          <n-select
            v-else-if="opt.type == 'select'"
            v-model:value="form[opt.key]"
            :options="opt.options"
            :disabled="opt.disabled || false"
            :clearable="opt.clearable === undefined ? true : opt.clearable"
            :clear-filter-after-select="opt.clearFilterAfterSelect || false"
            :multiple="opt.multiple"
            :placeholder="opt.placeholder || '请选择'"
            :remote="opt.remote || false"
            :filterable="opt.filterable || false"
            :size="opt.size || 'small'"
            :tag="opt.tag === undefined ? false : opt.tag"
            :show="opt.show"
            :show-arrow="opt.showArrow === undefined ? true : opt.showArrow"
            style="width: 100%"
            @search="handleSearch"
          >
          </n-select>
          <!-- 级联选择器 -->
          <n-cascader
            v-else-if="opt.type == 'cascader'"
            v-model:value="form[opt.key]"
            :multiple="opt.multiple || false"
            :placeholder="opt.placeholder || '请选择'"
            :options="opt.options"
            :disabled="opt.disabled || false"
            :cascade="opt.cascade == undefined ? true : opt.cascade"
            :check-strategy="opt.checkStrategy || 'all'"
            :show-path="opt.showPath"
            :label-field="opt.labelField || 'label'"
            :value-field="opt.valueField || 'value'"
            :children-field="opt.childrenField || 'children'"
            :allow-checking-not-loaded="opt.allowCheckingNotLoaded || false"
            :filterable="opt.filterable || false"
            :remote="opt.remote || true"
            :on-load="handleLoad"
            :size="opt.size || 'small'"
            style="width: 100%"
          />
          <!-- 时间选择器  data: opt.options.find((x) => x.value === form[opt.key]), -->
          <n-time-picker
            v-else-if="opt.type == 'timePicker'"
            v-model:formatted-value="form[opt.key]"
            :format="opt.format || 'HH:mm:ss'"
            :value-format="opt.valueFormat || 'HH:mm:ss'"
            :placeholder="opt.placeholder || '请选择时间'"
            :disabled="opt.disabled || false"
            :clearable="opt.clearable || true"
            :actions="opt.actions || null"
            :update-value-on-close="true"
            style="width: 100%"
            :size="opt.size || 'small'"
          />

          <!-- 日期选择器 -->
          <n-date-picker
            v-else-if="
              [
                'date',
                'datetime',
                'daterange',
                'datetimerange',
                'month',
                'year',
                'quarter',
              ].includes(opt.type)
            "
            v-model:formatted-value="form[opt.key]"
            :type="opt.type"
            :value-format="opt.valueFormat || 'yyyy-MM-dd'"
            :format="opt.format || 'yyyy-MM-dd'"
            :placeholder="opt.placeholder || '请选择日期'"
            :disabled="opt.disabled || false"
            :actions="opt.actions || null"
            :clearable="opt.clearable || true"
            :close-on-select="true"
            :shortcuts="opt.shortcuts || undefined"
            :update-value-on-close="true"
            style="width: 100%"
            size="small"
          />
          <!-- 开关 -->
          <n-switch
            v-else-if="opt.type == 'switch'"
            v-model:value="form[opt.key]"
            :disabled="opt.disabled"
            :size="opt.size || 'medium'"
            :rail-style="opt.railStyle"
          >
            <template #checked>
              {{ opt.openText || '是' }}
            </template>
            <template #unchecked>
              {{ opt.closeText || '否' }}
            </template>
          </n-switch>
      </n-grid>
    </n-form>
  </n-spin>
</template>
<script setup>
  import { TreeDataFlat } from '@/utils'
  const previewImageUrlRef = ref('')
  const showModalRef = ref(false)
  const formRef = ref(null)
  const emit = defineEmits([
    'change',
    'selectorAsynchronism',
    'onLoad',
    'callback',
    'cancel',
    'click',
    'mapClick',
  ])

  const props = defineProps({
    loading: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String,
      default: 'edit',
    },
    collapsed: {
      type: Boolean,
      default: false,
    },
    collapsedRows: {
      type: Number,
      default: 1,
    },
    inline: {
      type: Boolean,
    },
    form: {
      type: Object,
      required: true,
      default: () => ({}),
    },
    size: {
      type: String,
      default: 'small',
    },
    options: {
      type: Array,
      required: true,
    },
    rules: {
      type: Object,
      default: () => {
        return {}
      },
    },
    labelWidth: {
      type: String || undefined,
      default: 'auto',
    },
    xGap: {
      type: [Number, String],
      default: 12,
    },
    yGap: {
      type: Number,
      default: 0,
    },
    onLoad: {
      type: Function || undefined,
    },
    isShowFooter: {
      type: Boolean,
      default: true,
    },
  })

  const formCache = computed(() => {
    return { ...props.form }
  })

  watch(
    formCache,
    (newForm, oldForm) => {
      const keys = Object.keys(newForm)
      const key = keys.find(key => {
        return newForm[key] !== oldForm[key]
      })
      if (key) {
        emit(`change`, {
          category: key,
          value: newForm[key],
        })
      }
    },
    {
      deep: true,
    }
  )

  const setViewSpan = opt => {
    const { type, path, options } = opt
    const val = props.form[path]

    if (type === 'select') {
      let nameList = []
      if (opt.tag) {
        nameList = val
      } else {
        // 兼容多选
        const valList =
          val || val === 0 || val === '0' ? (val + '').split(',') : []
        nameList = (options || [])
          .filter(
            item =>
              valList.indexOf(item[[opt.valueField || 'value']] + '') != -1
          )
          .map(item => item[opt.labelField || 'label'])
      }

      return nameList.length > 0 ? nameList.join('，') : ''
    } else if (type === 'switch') {
      const checkedVal =
        opt.checkedValue === undefined ? true : opt.checkedValue
      const unCheckedVal =
        opt.checkedValue === undefined ? false : opt.checkedValue

      return val == checkedVal
        ? opt.openText || '是'
        : val == unCheckedVal
        ? opt.closeText || '否'
        : val
    } else if (type === 'cascader') {
      const childrenField =
        opt.childrenField === undefined ? 'children' : opt.childrenField
      const valueField = opt.valueField === undefined ? 'value' : opt.valueField
      const labelField = opt.labelField === undefined ? 'label' : opt.labelField
      const flatArr = TreeDataFlat(options || [], childrenField)
      const labelList = flatArr
        .filter(item => val.indexOf(item[valueField]) != -1)
        .map(item => item[labelField])

      return labelList.join(',')
    } else if (val === +val) {
      return val
    } else {
      return val?.length > 0 ? val : '-'
    }
  }

  const handleSearch = parameters => {
    emit(`selectorAsynchronism`, parameters)
  }
  const handleLoad = parameters => {
    return props.onLoad(parameters)
  }

  const handleClick = key => {
    emit('click', key)
  }

  // 验证
  const validate = () => {
    let res = null
    return formRef.value
      ?.validate(errors => {
        if (!errors) {
          // $message.success("Valid");
          res = true
        } else {
          console.log('errors>>>', errors)
          $message.error('请输入必填项')
          res = false
        }
      })
      .then(() => {
        return Promise.resolve(res)
      })
      .catch(error => {
        return Promise.resolve(res)
      })
  }

  // 清除验证结果
  const clearValidate = () => {
    formRef.value?.restoreValidation()
  }

  defineExpose({
    validate,
    clearValidate,
  })
</script>
<style lang="scss" scoped>
  .page-amap {
    // width: 100vh;
    width: -webkit-fill-available;
    height: 500px;
  }
  ::v-deep(.v-binder-follower-content) {
    // width: 100px;
    width: -webkit-fill-available;
  }
  .view-text {
    word-break: break-word;
  }
  ::v-deep {
    input {
      &[type='number'] {
        -moz-appearance: textfield;
      }
      &::-webkit-outer-spin-button,
      &::-webkit-inner-spin-button {
        -webkit-appearance: none;
      }
    }
  }
  .enclosure {
    margin-top: 5px;
    display: block;
  }
</style>
